from flask_login import current_user
from flask_restful import Resource, marshal_with, reqparse  # type: ignore
from controllers.errors.error import HttpAccountNotFound
from controllers.errors.roles_errors import HTTPSysMenuNotFoundError, HTTPSysRoleNotFoundError, HTTPDelBuildInRoleError
from core.roles.role_check import check_perms
from libs.login import login_required
from controllers.console import api
from services.errors.account import AccountNotFoundError
from services.errors.roles import SysMenuNotFoundError, SysRoleNotFoundError, DelBuildInRoleError
from werkzeug.exceptions import InternalServerError
from fields.roles.roles_fields_def import role_fields,role_page_fields
from services.role_service import RoleService

class RoleManangeApi(Resource):
    @login_required
    @check_perms(perms=["roles:list"])
    @marshal_with(role_page_fields)
    def get(self):
        parser = reqparse.RequestParser()
        parser.add_argument("id",type=str,required=False,location='args')
        parser.add_argument("name",type=str,required=False,location='args')
        parser.add_argument("code",type=str,required=False,location='args')
        parser.add_argument("menu_id",type=str,required=False,location='args')
        parser.add_argument("page",type=int,required=False,location='args',default=-1)
        parser.add_argument("page_size",type=int,required=False,location='args',default=-1)
        args = parser.parse_args()
        role_id = args.get("id")
        name = args.get("name")
        code = args.get("code")
        menu_id = args.get("menu_id")
        page = args.get("page",-1)
        page_size = args.get("page_size",-1)
        return RoleService.get_role_list(current_user.current_tenant_id,role_id,name,code,menu_id,page,page_size)
    
    @login_required
    @check_perms(perms=["roles:new"])
    @marshal_with(role_fields)
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument("name",type=str,required=True,location='json')
        parser.add_argument("code",type=str,required=True,location='json')
        parser.add_argument("remark",type=str,required=False,location='json')
        args = parser.parse_args()
        name = args.get("name")
        code = args.get("code")
        remark = args.get("remark")
        try:
            return RoleService.create_role(current_user,name,code,remark)
        except Exception as e:
            raise InternalServerError(str(e))
        
    @login_required
    @check_perms(perms=["roles:update"])
    @marshal_with(role_fields)
    def put(self):
        parser = reqparse.RequestParser()
        parser.add_argument("id",type=str,required=True,location='json')
        parser.add_argument("name",type=str,required=True,location='json')
        parser.add_argument("code",type=str,required=True,location='json')
        parser.add_argument("remark",type=str,required=False,location='json')
        parser.add_argument("menus",type=str,action='append',required=False,location='json')
        args = parser.parse_args()
        role_id = args["id"]
        name = args["name"]
        code = args["code"]
        remark = args.get("remark")
        menus = args.get("menus",[])
        try:
            return RoleService.update_role(current_user,role_id,name,code,remark,menus)
        except SysRoleNotFoundError as e:
            raise HTTPSysRoleNotFoundError(e.role_id)
        except SysMenuNotFoundError as e:
            raise HTTPSysMenuNotFoundError(e.menu_id)
        except Exception as e:
            raise InternalServerError(str(e))
        
    @login_required
    @check_perms(perms=["roles:del"])
    def delete(self):
        parser = reqparse.RequestParser()
        parser.add_argument("id",type=str,required=True,location='json')
        args = parser.parse_args()
        role_id = args.get("id")
        try:
            return RoleService.delete_role(current_user,role_id)
        except DelBuildInRoleError:
            raise HTTPDelBuildInRoleError()
        except Exception as e:
            raise InternalServerError(str(e))
        
class AccountRoleApi(Resource):
    @login_required
    @check_perms(perms=["account:roles:read"])
    @marshal_with(role_fields)
    def get(self,account_id):
        try:
            return RoleService.get_account_roles(current_user.current_tenant_id,account_id)
        except Exception as e:
            raise InternalServerError(str(e))
        
    @login_required
    @check_perms(perms=["account:roles:create"])
    @marshal_with(role_fields)
    def put(self,account_id):
        parser = reqparse.RequestParser()
        parser.add_argument("role_ids",type=str,action='append',default=[],required=True,location='json')
        args = parser.parse_args()
        role_ids = args.get("role_ids",[])
        try:
            return RoleService.update_account_roles(current_user.current_user_id,account_id,role_ids)
        except AccountNotFoundError as e:
            raise HttpAccountNotFound(e.account_id)
        except Exception as e:
            raise InternalServerError(str(e))
        
    @login_required
    @check_perms(perms=["account:roles:del"])
    @marshal_with(role_fields)
    def delete(self,account_id):
        parser = reqparse.RequestParser()
        parser.add_argument("role_ids",type=str,action='append',default=[],required=True,location='json')
        args = parser.parse_args()
        role_ids = args.get("role_ids",[])
        try:
            return RoleService.del_account_roles(current_user.current_user_id,account_id,role_ids)
        except AccountNotFoundError as e:
            raise HttpAccountNotFound(e.account_id)
        except Exception as e:
            raise InternalServerError(str(e))
    
    
api.add_resource(AccountRoleApi, "/accounts/<account_id>/roles")
api.add_resource(RoleManangeApi, "/roles")